#ifndef THREADPOOL
#define THREADPOOL

#include <pthread.h>
#include <queue>
#include "mutex_guard.h"
#include "condition.h"

template<typename T>
class ThreadPool {
public:
    ThreadPool(int thread_number = 8, int max_requests = 10000);

    ~ThreadPool();

    bool append(T *request);

private:
    // we have to use this during Constructor, so it has to be static
    static void* worker(void *arg);  
    void run();

private:
    int m_thread_number; //线程数量
    int m_max_requests; //最大请求数

    pthread_t *m_threads;  //线程号数组
    std::queue<T *> m_workqueue; //工作队列

    Mutex m_workqueue_locker;
    Condition m_workqueue_condition;

    bool m_stop; 
};

//构造函数，创建时就构造线程
template<typename T>
ThreadPool<T>::ThreadPool(int thread_number, int max_requests) :
        m_thread_number(thread_number), 
        m_max_requests(max_requests), 
        m_stop(false), 
        m_threads(NULL),
        m_workqueue_locker(),
        m_workqueue_condition(m_workqueue_locker)
    {
    if ((thread_number <= 0) || (max_requests <= 0)) {
        throw std::exception();
    }

    m_threads = new pthread_t[m_thread_number];
    if (!m_threads) {
        throw std::exception();
    }
    
    for (int i = 0; i < thread_number; ++i) {
        // printf("create the %dth thread\n", i);
        if (pthread_create(m_threads + i, NULL, worker, this) != 0) { // 线程传入worker静态函数，参数为本身
            delete[] m_threads;
            throw std::exception();
        }
        // if (pthread_detach(m_threads[i])){
        //     delete[] m_threads;
        //     throw std::exception();
        // }
    }
}

template<typename T>
ThreadPool<T>::~ThreadPool() {
    m_stop = true;
    {
        MutexGuard MutexGuard(m_workqueue_locker);
        m_workqueue_condition.BroadCast();
    }
    for(int i=0; i<m_thread_number; ++i){
        pthread_join(m_threads[i], NULL);
    }
    printf("Thread pool destroy !\n");
    delete[] m_threads;
}

template<typename T>
void* ThreadPool<T>::worker(void *arg) {
    ThreadPool* pool = static_cast<ThreadPool *>(arg);
    pool->run(); 
    return pool;
}

template<typename T>
void ThreadPool<T>::run() {
    while (!m_stop) {
        T* request = nullptr;
        {
            MutexGuard mutexGuard(m_workqueue_locker);
            while(!m_stop && m_workqueue.empty()) {
                m_workqueue_condition.Wait();
            }
            if(m_stop){
                break;
            }
            request = m_workqueue.front();
            m_workqueue.pop();
        }
        if(request){
            request->handleRequest(); //处理事务
        }
    }
    printf("thread exit\n");
    pthread_exit(NULL);
}

template<typename T>
bool ThreadPool<T>::append(T *request) {
    MutexGuard MutexGuard(m_workqueue_locker);
    if (m_workqueue.size() > m_max_requests) {
        return false;
    }
    m_workqueue.push(request);
    m_workqueue_condition.BroadCast();
    return true;
}

#endif